home *** CD-ROM | disk | FTP | other *** search
- /*
- **
- ** $Id: am.c,v 1.2 1995/10/07 02:52:18 chris Exp $
- ** $Revision: 1.2 $
- **
- ** $Filename: developer/am.c $
- ** $Author: chris $
- ** $Date: 1995/10/07 02:52:18 $
- ** $Portability: ANSI $
- **
- ** Ein kleiner Anrufbeantworter, setzt auf CAPI 2.0 auf.
- **
- ** THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF RELOG AG.
- **
- ** COPYRIGHT (C) 1992-1996 BY RELOG AG, ZUERICH. ALL RIGHTS RESERVED.
- ** NO PART OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
- ** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PERMISSION
- ** OF RELOG AG.
- **
- */
-
- #include <exec/types.h>
- #include <proto/exec.h>
- #include <dos/dos.h>
-
- #include <stdio.h>
- #include <string.h>
-
- #include "os.h"
- #include "alaw.h"
- #include "capi-usr.h"
-
- #define _AM
- #include "am.h"
- #include "arexx.h"
- #include "bchanneljobs.h"
- #include "process.h"
-
-
- static struct AnsweringMachine am =
- {
- 1, /* Controller */
- "8", /* MSN */
- "limmathotline.amrx", /* REXX-Script */
- };
-
-
- /*
- ** Locals
- */
- static U16 applID;
- static U32 capiproc;
- static BOOL running = TRUE;
-
-
- /****************************************************************************
- ** Klein- nach Grossbuchstaben wandeln. $$$ Kann keine Umlaute
- */
-
- static U8 ToUpper( U8 c )
- {
- return (U8)(((c >= 'a') && (c <= 'z')) ? c + 'A' - 'a' : c);
- }
-
-
- /****************************************************************************
- ** Send a CAPI message to the CAPI driver
- */
-
- U32
- SendCAPIMessage( CAPI_MESSAGE *msg, U8 *end )
- {
- msg->TotalLength = end - (U8 *)msg;
- return U_CAPI_PUT_MESSAGE( applID, msg );
- }
-
-
- /****************************************************************************
- ** Aus einem Array von CAPI-`struct's einen Zeiger auf die <num>te
- ** struct (d.h. auf das Längenbyte) zurückgeben
- */
-
- static U8 *GetStruct( U8 *ptr, int num )
- {
- while (num > 0)
- {
- if (*ptr == 0xFF)
- ptr += (GET_U16(ptr+1) + 3);
- else
- ptr += *ptr + 1;
-
- num--;
- }
-
- return ptr;
- }
-
-
- /****************************************************************************
- ** Add a null-terminated string as a struct to a CAPI message
- */
-
- static VOID AddStructString( U8 **paraptr, U8 *string )
- {
- U8 *para = *paraptr;
- int len = strlen( string );
-
- if (len < 0xFF)
- {
- ADD_PARA( para, U8, len );
- }
- else
- {
- ADD_PARA( para, U8, 0xFF ); /* Escape-Zeichen für 16Bit-Länge */
- ADD_PARA( para, U16, len );
- }
-
- strcpy( para, string );
-
- *paraptr = para + len;
- }
-
-
- /****************************************************************************
- ** Testen, ob eine MSN auf ein am-Entity passt. `msn' ist dabei ein
- ** CAPI struct, mit Längenbyte im ersten Byte.
- */
-
- static BOOL CheckMSN( struct AnsweringMachine *am, U8 *ist )
- {
- if (ToUpper( am->MSN[0] ) != 'X') /* `Alle MSNs akzeptieren' ? */
- {
- U8 *p1, *p2, len = (U8)strlen( am->MSN );
-
- /* Ende der Called Party Number im CAPI struct */
- p1 = ist + ist[0] + 1;
-
- /* Ende der MSN in unserer Konfiguration */
- p2 = am->MSN + len;
-
- /*
- ** Es werden nur soviele Zeichen verglichen,
- ** wie die kürzere der beiden Nummern enthält.
- ** Dadurch kann der Benutzer beispielsweise
- ** statt seiner EAZ die ganze Nummer eingeben,
- ** und ein Anruf wird trotzdem richtig erkannt.
- */
- if (len > ist[0])
- len = ist[0];
-
- while (len)
- {
- if (*--p1 != *--p2)
- return FALSE; /* Falsche MSN */
- len--;
- }
- }
-
- return TRUE; /* Nummer stimmt überein */
- }
-
-
- /****************************************************************************
- ** Ein Zeichen aus dem Keybuffer lesen und zurückgeben
- */
-
- static U8 GetKey( struct AnsweringMachine *am )
- {
- USES_DISABLE
- U8 key = '-'; /* "-" heisst "keine Taste gedrückt" */
-
- DISABLE;
- if (am->KeyBufferSize > 0)
- {
- key = am->KeyBuffer[0];
- memmove( am->KeyBuffer, am->KeyBuffer+1, am->KeyBufferSize );
- am->KeyBufferSize--;
- }
- ENABLE;
-
- return key;
- }
-
-
- /****************************************************************************
- ** Alle Zeichen aus dem Keybuffer entfernen
- */
-
- static VOID FlushKeyBuffer( struct AnsweringMachine *am )
- {
- am->KeyBufferSize = 0;
- }
-
-
- /****************************************************************************
- ** Auf ein Zeichen einer Auswahl warten. Falls keys ein leerer Strig
- ** ist, wartet die Funktion auf eine beliebige Taste. Falls keys das
- ** Zeichen '-' enthält, kehrt diese Funktion zurück, sobald ein SIGF_
- ** SINGLE empfangen wurde, sonst wartet sie.
- ** timeout ist in Sekunden. 0 = kein Timeout.
- */
-
- static U8 WaitKeys( struct AnsweringMachine *am, U8 *keys, S32 timeout )
- {
- S32 doomsday;
-
- for (doomsday = 0;; doomsday++)
- {
- U32 signals = CheckSignal( SIGBREAKF_CTRL_C | SIGF_SINGLE );
- U8 key;
-
- if (timeout != 0)
- {
- if (doomsday >= (timeout * 4))
- {
- printf( "WaitKeys(): timeout reached.\n" );
- return '-';
- }
- }
-
- if (signals & SIGBREAKF_CTRL_C)
- return '-'; /* $$$ Macht das Sinn ? */
-
- if (signals & SIGF_SINGLE)
- if (strchr( keys, '-' ))
- return '-';
-
- if ((key = GetKey( am )) != '-')
- {
- if ((keys[0] == '\0') || (strchr( keys, key ) != NULL))
- return key;
- }
- else Delay( TICKS_PER_SECOND / 4 );
- }
- }
-
-
- /****************************************************************************
- ** REXX-Kommando: Background <file> <volume> [LOOP]
- */
-
- S32 RXFunc_Background( char *args, struct AnsweringMachine *am )
- {
- char filename[PATHNAMESIZE];
-
- if (ARexx_GetString( &args, filename, sizeof( filename ) ))
- {
- S32 volume;
-
- if (ARexx_GetInteger( &args, &volume ))
- {
- char loop[16];
- U16 jobflags = JOBF_WRITE | JOBF_AUTOFREE;
-
- loop[0] = '\0';
- if (ARexx_GetString( &args, loop, sizeof( loop ) ))
- {
- if (!stricmp( loop, "LOOP" ))
- jobflags |= JOBF_LOOP;
- }
-
- printf( "Background: file='%s', volume=%ld, loop='%s'\n", filename, volume, loop );
-
- if (volume > 100)
- volume = 100;
- if (volume < 0)
- volume = 0;
-
- volume = (volume * B_VOLUME_MAX) / 100;
-
- if (am->BGJob != NULL)
- {
- BChannel_FreeJob( am->BGJob );
- /* am->BGJob = NULL; */
- }
-
- if (am->BGJob = BChannel_AddJob( am->BChannel, filename, jobflags, (U16)volume, am->Process ))
- return RC_OK;
-
- return RC_WARN;
- }
- }
-
- return RC_FATAL;
- }
-
-
- /****************************************************************************
- ** REXX-Kommando: Fade <endvolume>
- */
-
- S32 RXFunc_Fade( char *args, struct AnsweringMachine *am )
- {
- S32 volume;
-
- if (ARexx_GetInteger( &args, &volume ))
- {
- BOOL waiting = TRUE;
- USES_DISABLE
-
- printf( "Fade: volume=%ld\n", volume );
-
- if (volume > 100)
- volume = 100;
- if (volume < 0)
- volume = 0;
-
- volume = (volume * B_VOLUME_MAX) / 100;
-
- DISABLE;
- if (am->BGJob != NULL)
- am->BGJob->EndVolume = (U16)volume;
- ENABLE;
-
- while (waiting)
- {
- DISABLE;
- if (am->BGJob != NULL)
- {
- if (am->BGJob->ActVolume == am->BGJob->EndVolume)
- waiting = FALSE;
- }
- else
- {
- waiting = FALSE;
- }
- ENABLE;
- Delay( TICKS_PER_SECOND );
- }
-
- return RC_OK;
- }
- return RC_FATAL;
- }
-
-
- /****************************************************************************
- ** REXX-Kommando: Hangup [cause]
- */
-
- S32 RXFunc_HangUp( char *args, struct AnsweringMachine *am )
- {
- struct
- {
- CAPI_MESSAGE Msg;
- U8 Para[8];
- } disconnect_b3_req;
-
- U8 *para = disconnect_b3_req.Para;
-
- S32 cause = 16; /* NORMAL CALL CLEARING */
-
- ARexx_GetInteger( &args, &cause );
-
- FlushKeyBuffer( am );
- printf( "Hangup: cause=%ld\n", cause );
-
- disconnect_b3_req.Msg.Command = CAPICMD_DISCONNECT_B3;
- disconnect_b3_req.Msg.Subcommand = CAPISUBCMD_REQ;
-
- ADD_PARA( para, U32, am->NCCI ); /* NCCI des aktuellen Calls */
- ADD_PARA( para, U8, 0 ); /* NCPI brauchen wir nicht */
-
- SendCAPIMessage( &disconnect_b3_req.Msg, para );
-
- return RC_OK;
- }
-
-
- /****************************************************************************
- ** REXX-Kommando: Play <file> <volume> [keys]
- */
-
- S32 RXFunc_Play( char *args, struct AnsweringMachine *am )
- {
- char filename[PATHNAMESIZE];
-
- if (ARexx_GetString( &args, filename, sizeof( filename ) ))
- {
- S32 volume;
-
- if (ARexx_GetInteger( &args, &volume ))
- {
- struct BChannel_Job *job;
- char keys[20];
-
- keys[0] = '\0';
- if (ARexx_GetString( &args, keys, sizeof( keys ) ))
- {
- }
-
- printf( "Play: file='%s', volume=%ld, keys='%s'\n", filename, volume, keys );
-
- if (volume > 100)
- volume = 100;
- if (volume < 0)
- volume = 0;
-
- volume = (volume * B_VOLUME_MAX) / 100;
-
- FlushKeyBuffer( am );
- if (job = BChannel_AddJob( am->BChannel, filename, JOBF_WRITE, (U16)volume, am->Process ))
- {
- rexx_resultstring[0] = WaitKeys( am, keys, 0 );
- rexx_resultstring[1] = '\0';
-
- BChannel_FreeJob( job );
- return RC_OK;
- }
-
- return RC_WARN;
- }
- }
-
- return RC_FATAL;
- }
-
-
- /****************************************************************************
- ** REXX-Kommando: Record <file> <maxtime> [keys]
- */
-
- S32 RXFunc_Record( char *args, struct AnsweringMachine *am )
- {
- char filename[PATHNAMESIZE];
-
- if (ARexx_GetString( &args, filename, sizeof( filename ) ))
- {
- S32 maxtime;
-
- if (ARexx_GetInteger( &args, &maxtime ))
- {
- struct BChannel_Job *job;
- char keys[20];
-
- keys[0] = '\0';
- if (ARexx_GetString( &args, keys, sizeof( keys ) ))
- {
- }
-
- printf( "Record: file='%s', maxtime=%ld, keys='%s'\n", filename, maxtime, keys );
-
- FlushKeyBuffer( am );
- if (job = BChannel_AddJob( am->BChannel, filename, JOBF_READ, B_VOLUME_MAX, am->Process ))
- {
- rexx_resultstring[0] = WaitKeys( am, keys, maxtime );
- rexx_resultstring[1] = '\0';
-
- BChannel_FreeJob( job );
- return RC_OK;
- }
-
- return RC_WARN;
- }
- }
-
- return RC_FATAL;
- }
-
-
- /****************************************************************************
- ** REXX-Kommando: WaitKey
- */
-
- S32 RXFunc_WaitKey( char *args, struct AnsweringMachine *am )
- {
- printf( "WaitKey\n" );
-
- FlushKeyBuffer( am );
-
- rexx_resultstring[0] = WaitKeys( am, "", 0 );
- rexx_resultstring[1] = '\0';
-
- return RC_OK;
- }
-
-
- /****************************************************************************
- ** LISTEN_REQ an CAPI abschicken
- */
-
- static VOID ListenReq( U8 controller )
- {
- struct
- {
- CAPI_MESSAGE Msg;
- U8 Para[32]; /* $$$ Rough guess */
- } listen_req;
-
- U8 *para = listen_req.Para;
-
- listen_req.Msg.Command = CAPICMD_LISTEN;
- listen_req.Msg.Subcommand = CAPISUBCMD_REQ;
-
- ADD_PARA( para, U32, controller ); /* Controller */
-
- ADD_PARA( para, U32, 0xFFFFFFFF ); /* Info mask: alles */
-
- ADD_PARA( para, U32, /* CIP mask: Nur Gespräche */
- (1UL << CAPI_CIP_SPEECH)
- | (1UL << CAPI_CIP_AUDIO31)
- | (1UL << CAPI_CIP_TELEPHONY) );
-
- ADD_PARA( para, U32, 0 ); /* CIP mask 2: reserviert */
- ADD_PARA( para, U8, 0 ); /* Calling party number */
- ADD_PARA( para, U8, 0 ); /* Calling party subaddress */
-
- SendCAPIMessage( &listen_req.Msg, para );
- }
-
-
- /****************************************************************************
- ** Touchtone-Dekodierung einschalten (79)
- */
-
- static VOID TouchtoneDecoder( U32 ncci, BOOL onoff )
- {
- struct
- {
- CAPI_MESSAGE Msg;
- U8 Para[32]; /* $$$ Rough guess */
- } facility_req;
-
- U8 *para = facility_req.Para;
-
- facility_req.Msg.Command = CAPICMD_FACILITY;
- facility_req.Msg.Subcommand = CAPISUBCMD_REQ;
-
- ADD_PARA( para, U32, ncci );
- ADD_PARA( para, U16, 1 ); /* Facility Selector: DTMF */
-
- ADD_PARA( para, U8, 7 ); /* Struct length */
- ADD_PARA( para, U16, onoff ? 1 : 2 ); /* Function: Start/Stop DTMF listen */
- ADD_PARA( para, U16, 40 ); /* Time in ms for one digit (ignored) */
- ADD_PARA( para, U16, 40 ); /* Time in ms between digits (ignored) */
- ADD_PARA( para, U8, 0 ); /* Struct digits (ignored) */
-
- SendCAPIMessage( &facility_req.Msg, para );
- }
-
-
- /****************************************************************************
- ** Eine CAPI-Message behandeln
- */
-
- static BOOL HandleCAPIMessage( struct AnsweringMachine *am, CAPI_MESSAGE *msg )
- {
- UBYTE *para = (UBYTE *)(msg+1);
- BOOL running = TRUE;
-
- switch (msg->Subcommand)
- {
- case CAPISUBCMD_CONF:
- switch (msg->Command)
- {
- /*
- ** DATA_B3_CONF (Seite 33)
- */
- case CAPICMD_DATA_B3:
- {
- U32 ncci;
- U16 handle;
-
- GET_PARA( para, U32, ncci );
- GET_PARA( para, U16, handle );
-
- BChannel_DataB3Conf( ncci );
- }
- break;
-
-
- /*
- ** LISTEN_CONF (Seite 54)
- */
- case CAPICMD_LISTEN:
- {
- U32 controller;
- U16 info;
-
- GET_PARA( para, U32, controller );
- GET_PARA( para, U16, info );
-
- if (info != CAPI_00_REQUEST_ACCEPTED)
- {
- printf( "LISTEN_REQ failed (error 0x%04x)\n", info );
- running = FALSE;
- }
- }
- break;
-
-
- /*
- ** FACILITY_CONF (Seite 45)
- */
- case CAPICMD_FACILITY:
- {
- U32 ncci;
- U16 info;
-
- GET_PARA( para, U32, ncci );
- GET_PARA( para, U16, info );
-
- if (info != CAPI_00_REQUEST_ACCEPTED)
- {
- printf( "FACILITY_REQ for ncci 0x%08lx failed (error 0x%04x)\n", ncci, info );
- running = FALSE;
- }
- }
- break;
-
-
- default:
- INTERNAL_ERROR;
- break;
-
- }
- break;
-
-
-
-
- case CAPISUBCMD_IND:
- msg->Subcommand = CAPISUBCMD_RESP; /* Für Antwort-Messages */
-
- switch (msg->Command)
- {
- /*
- ** CONNECT_IND (Seite 19)
- */
- case CAPICMD_CONNECT:
- {
- U32 plci;
- U16 cip;
- U16 reject = CAPI_REJECT_IGNORE;
-
- GET_PARA( para, U32, plci );
- GET_PARA( para, U16, cip );
-
- if (CheckMSN( am, GetStruct( para, 0 )))
- {
- if (am->PState == P0_IDLE)
- {
- U8 *str;
-
- am->PLCI = plci;
- am->PState = P2_CONNECT_INDICATION;
-
-
- /*
- ** Calling Party Number übernehmen. Die ersten
- ** zwei Bytes der struct enthalten Type of Number
- ** und Presentation Indicator, und werden ignoriert.
- */
- str = GetStruct( para, 1 );
- if (str[0] >= 2) /* Falls Nummer vorhanden */
- {
- memcpy( am->CallingNumber, str + 1 + 2, str[0] - 2 );
- am->CallingNumber[str[0] - 2] = '\0';
- }
- else
- am->CallingNumber[0] = '\0';
-
- printf( "Got a call from %s\n", am->CallingNumber );
-
- reject = CAPI_REJECT_ACCEPT;
- am->PState = P4_CALL_ACCEPTED;
- }
- }
-
-
- /*
- ** Entsprechende CONNECT_RESP-Message vorbereiten
- */
- para = (U8 *)(msg+1) + 4; /* PLCI übernehmen */
- ADD_PARA( para, U16, reject );
-
- ADD_PARA( para, U8, 9 ); /* B Protocol: Struct-Länge */
- ADD_PARA( para, U16, CAPI_B1PROT_TRANSP64 ); /* B1 protocol */
- ADD_PARA( para, U16, CAPI_B2PROT_TRANSP ); /* B2 protocol */
- ADD_PARA( para, U16, CAPI_B3PROT_TRANSP ); /* B3 protocol */
- ADD_PARA( para, U8, 0 ); /* B1 configuration: leer */
- ADD_PARA( para, U8, 0 ); /* B2 configuration: leer */
- ADD_PARA( para, U8, 0 ); /* B3 configuration: leer */
-
- ADD_PARA( para, U8, 0 ); /* Struct ConnectedNumber */
- ADD_PARA( para, U8, 0 ); /* Struct ConnectedSubaddress */
- ADD_PARA( para, U8, 0 ); /* Struct LLC */
- ADD_PARA( para, U8, 0 ); /* Struct AdditionalInfo */
- }
- break;
-
-
- /*
- ** CONNECT_ACTIVE_IND (Seite 22)
- */
- case CAPICMD_CONNECT_ACTIVE:
- {
- U32 plci;
-
- GET_PARA( para, U32, plci );
- am->PState = P_ACTIVE;
- }
- break;
-
-
- /*
- ** CONNECT_B3_IND (Seite 28)
- */
- case CAPICMD_CONNECT_B3:
- {
- U32 ncci;
-
- GET_PARA( para, U32, ncci );
- /* GET_PARA( para, U32, ncpi ); */
-
- am->NCCI = ncci;
-
- if ((am->BChannel = BChannel_New( ncci )) != NULL)
- {
- }
-
- ADD_PARA( para, U16, CAPI_REJECT_ACCEPT );
- ADD_PARA( para, U8, 0); /* Kein NCPI */
-
- }
- break;
-
-
- /*
- ** CONNECT_B3_ACTIVE_IND (Seite 24)
- */
- case CAPICMD_CONNECT_B3_ACTIVE:
- {
- char buf[256];
- U32 ncci;
-
- GET_PARA( para, U32, ncci );
- printf( "B-channel activated.\n" );
-
- am->Process = Process_Create( NULL, am, "AM-REXX", 2 );
- Process_WakeUp( am->Process );
-
- TouchtoneDecoder( ncci, TRUE );
-
-
- /*
- ** PARSE arg callednumber callingnumber
- */
- sprintf( buf, "limmathotline.amrx %s %s", "?", am->CallingNumber );
-
- printf( "Launching Rexx: %s\n", buf );
- ARexx_LaunchScript( Process_GetRexxPort( am->Process ), buf );
- }
- break;
-
-
- /*
- ** DATA_B3_IND (Seite 34)
- */
- case CAPICMD_DATA_B3:
- {
- U32 ncci;
- U8 *data;
- U16 size, handle, flags;
-
- GET_PARA( para, U32, ncci );
- GET_PARA( para, U8 *, data );
- GET_PARA( para, U16, size );
- GET_PARA( para, U16, handle );
- GET_PARA( para, U16, flags );
-
- BChannel_DataB3Ind( ncci, data, size );
-
- para = (U8 *)(msg+1) + 4; /* Nach NCCI */
- ADD_PARA( para, U16, handle );
- }
- break;
-
-
- /*
- ** DISCONNECT_IND (Seite 42)
- */
- case CAPICMD_DISCONNECT:
- {
- U32 plci;
- U16 reason;
-
- GET_PARA( para, U32, plci );
- GET_PARA( para, U16, reason );
-
- if (am->BChannel != NULL)
- {
- BChannel_Free( am->BChannel );
- am->BChannel = NULL;
- }
-
- am->NCCI = 0;
-
- am->PState = P0_IDLE;
- am->PLCI = 0;
-
- Process_Delete( am->Process );
-
- para = (U8 *)(msg+1) + 4; /* DISCONNECT_RESP hat nur PLCI */
- printf( "Connection terminated.\n" );
- }
- break;
-
-
- /*
- ** DISCONNECT_B3_IND (Seite 38)
- */
- case CAPICMD_DISCONNECT_B3:
- {
- U32 ncci;
- U16 reason_b3;
-
- GET_PARA( para, U32, ncci );
- GET_PARA( para, U16, reason_b3 );
-
- am->NCCI = 0;
-
- Process_Delete( am->Process );
-
- if (am->BChannel != NULL)
- {
- BChannel_Free( am->BChannel );
- am->BChannel = NULL;
- }
-
- para = (U8 *)(msg+1) + 4; /* DISCONNECT_B3_RESP hat nur NCCI */
- printf( "B-channel deactivated.\n" );
- }
- break;
-
-
- /*
- ** FACILITY_IND
- */
- case CAPICMD_FACILITY:
- {
- U32 ncci;
- U16 type;
-
- GET_PARA( para, U32, ncci );
- GET_PARA( para, U16, type );
-
- switch (type)
- {
- case 1: /* DTMF */
- {
- U8 numkeys, key;
-
- GET_PARA( para, U8, numkeys );
-
- while (numkeys)
- {
- USES_DISABLE
- char buf[PATHNAMESIZE];
-
- GET_PARA( para, U8, key );
-
- /*
- ** Key an Keybuffer anhängen
- */
- DISABLE;
- if (am->KeyBufferSize < sizeof( am->KeyBuffer ))
- {
- am->KeyBuffer[am->KeyBufferSize] = key;
- am->KeyBufferSize++;
- }
- ENABLE;
-
- if ((key >= '0') && (key <= '9'))
- {
- sprintf( buf, "Ansagen/Keys/KEY-%lc", (U32)key );
- BChannel_AddJob( am->BChannel, buf, JOBF_WRITE, B_VOLUME_MAX, 0 );
- }
- numkeys--;
- }
- }
- break;
-
- default:
- printf( "Unknown facility %ld\n", (U32)type );
- break;
- }
- }
- break;
-
-
- /*
- ** INFO_IND
- */
- case CAPICMD_INFO:
- {
- U32 plci;
- U16 infonumber;
- U8 infosize;
-
- GET_PARA( para, U32, plci );
- GET_PARA( para, U16, infonumber );
- GET_PARA( para, U8, infosize ); /* Grösse der Info-Struct */
-
- para = (U8 *)(msg+1) + 4; /* INFO_RESP: Nur PLCI */
- }
- break;
-
-
- default:
- INTERNAL_ERROR;
- break;
- }
-
-
- /*
- ** Vorbereitete Message (normalerweise Antwortmessage auf _IND) senden.
- ** Para zeigt hier auf das Ende der zu sendenden Message.
- */
- SendCAPIMessage( msg, para );
- break;
- }
-
- return running;
- }
-
-
- /****************************************************************************
- ** Diese Funktion wird vom CAPI-Treiber aufgerufen, wenn eine neue
- ** CAPI-Message bereitliegt. Sie weckt einfach unseren CAPI-Prozess.
- */
-
- static void __saveds MySignalHandler( unsigned short applID, unsigned long para )
- {
- Process_WakeUp( para );
- }
-
-
- /****************************************************************************
- ** Diese Funktion wird vom CAPI-Prozess aufgerufen, wenn er aufgeweckt
- ** wurde.
- */
-
- static BOOL __saveds CAPIProcFunc( VOID *para )
- {
- CAPI_MESSAGE *msg;
-
- while (U_CAPI_GET_MESSAGE( applID, &msg ) == 0)
- {
- running = HandleCAPIMessage( para, msg );
- }
-
- return TRUE;
- }
-
-
- /****************************************************************************
- ** Das Hauptprogramm
- */
-
- int main( int argc, char **argv )
- {
- U16 error;
-
-
- if (!((argc == 1) || ((argc == 2) && strcmp( argv[1], "?")) || (argc > 2)))
- {
- printf( "Usage: %s [number]\n", argv[0] );
- return 10;
- }
-
-
- /*
- ** Als erstes finden wir raus, ob in diesem Rechner überhaupt ein
- ** CAPI-Treiber installiert ist.
- */
- if (U_CAPI_INSTALLED())
- {
- printf( "No CAPI driver installed!\n" );
- return 10;
- }
-
-
- /*
- ** CAPI initialisieren. Dies muss ganz am Anfang geschehen, bevor
- ** irgendwelche CAPI-Funktionen (ausser U_CAPI_INSTALLED) aufgerufen
- ** werden.
- */
- if ((error = U_CAPI_REGISTER( 2, 2, B_BLOCKSIZE, &applID )))
- {
- printf( "Can't initialize CAPI, error 0x%lx\n", error );
- return 10;
- }
-
- ARexx_Init();
- ALAW_Init();
-
-
- /*
- ** Infos über den CAPI-Treiber ausgeben
- */
- {
- U32 ver[4];
- U8 manu[64];
-
- U_CAPI_GET_VERSION( ver );
- U_CAPI_GET_MANUFACTURER( manu );
-
- printf( "Driver: %s\nVersion %ld.%ld (internal revision %ld.%ld)\n\n",
- manu, ver[0], ver[1], ver[2], ver[3] );
- }
-
-
- /*
- ** CAPI-Handler-Prozess und Callback-Funktion initialisieren.
- */
- if (capiproc = Process_Create( CAPIProcFunc, &am, "AM-CAPI", 15 ))
- {
- U_CAPI_SET_SIGNAL( applID, (ULONG)MySignalHandler, capiproc );
-
- ListenReq( am.Controller );
-
- Wait( SIGBREAKF_CTRL_C );
-
- Process_Delete( capiproc );
- capiproc = (U32)NULL;
- }
- else
- {
- printf( "Can't create CAPI handler process\n" );
- }
-
-
- ALAW_Exit();
- ARexx_Exit();
-
- /*
- ** CAPI schliessen.
- */
- U_CAPI_RELEASE( applID );
-
- return 0;
- }
-
-